<template>
  <div class="workflow-tool">
    <el-popover :visible="visible" placement="bottom-start" :width="900" trigger="click">
      <template #reference>
        <el-button @click="visible = !visible" :type="editRow.id ? 'primary' : 'info'">
          {{ setToolTitle }}
          <el-icon class="ml10">
            <ArrowDown />
          </el-icon>
        </el-button>
      </template>
      <div class="flex align-center">
        <el-input
          v-model="search"
          @keyup="searchEvent"
          style="width: 250px"
          placeholder="搜索全表"
          clearable
          :prefix-icon="Search"
          @clear="searchEvent"
        />
        <el-button circle :icon="Close" @click="visible = false" class="ml-auto" />
      </div>
      <vxe-table
        size="mini"
        max-height="400"
        :column-config="{ useKey: true }"
        :row-config="{ useKey: true, keyField: 'id' }"
        :radio-config="{ checkRowKey: editRow.id, trigger: 'row' }"
        :data="list"
        @radio-change="onRadioChange"
      >
        <vxe-column width="45" type="radio" title="选择" />
        <vxe-column width="150" field="name" title="名称" type="html" />
        <vxe-column width="300" field="ins_name" title="实体" type="html" />
        <vxe-column width="100" field="flag" title="标签" type="html" />
        <vxe-column width="150" field="created_on" title="时间" type="html" />
        <!--        <vxe-column field="descript" title="备注" type="html" />-->
        <vxe-column title="操作" width="100" v-if="!queryId">
          <template #default="{ row }">
            <el-button
              link
              type="warning"
              size="small"
              @click.stop="onCopyRow(row)"
              :disabled="copyId === row.id"
            >
              复制
            </el-button>
            <el-button class="ml5" link type="danger" size="small" @click.stop="onDeleteRow(row)">
              删除
            </el-button>
          </template>
        </vxe-column>
      </vxe-table>
    </el-popover>
    <div class="flex align-center flex-shrink ml10" style="width: 200px">
      <span class="flex-shrink">名称：</span>
      <el-input v-model="editRow.name" placeholder="流程名称" />
    </div>
    <div class="flex align-center flex-shrink ml10" style="width: 140px">
      <span class="flex-shrink">标签：</span>
      <el-input v-model="editRow.flag" placeholder="流程标签" />
    </div>
    <div class="flex align-center flex-shrink ml10" style="width: 200px">
      <span class="flex-shrink">实例：</span>
      <el-select v-model="editRow.ins_name" filterable>
        <el-option
          v-for="(option, index) in ins_names"
          :key="index"
          :value="option.value"
          :label="option.label"
        />
      </el-select>
    </div>
    <div class="workflow-tool-right">
      <div class="flex align-center flex-shrink ml10" style="width: 180px">
        <span class="flex-shrink">线性：</span>
        <el-select v-model="connector" @change="onConnectorChange">
          <el-option value="Bezier" label="Bezier" />
          <el-option value="Flowchart" label="Flowchart" />
          <el-option value="StateMachine" label="StateMachine" />
          <el-option value="Straight" label="Straight" />
        </el-select>
      </div>
      <div
        class="workflow-tool-icon"
        v-for="(v, k) in state.toolList"
        :key="k"
        :title="v.title"
        @click="onToolClick(v.fnName)"
        :class="{
          danger: v.fnName === 'del',
          primary: v.fnName === 'submit',
          warning: v.fnName === 'copy'
        }"
        v-show="!v.hide"
      >
        <SvgIcon :name="v.icon" />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts" name="pagesWorkflowTool">
import type { VxeTableEvents } from 'vxe-table'
import type { WorkflowDesignRow } from '@/types/custom'
import { computed, nextTick, onMounted, reactive, ref, unref, watch } from 'vue'
import { useWfApi } from '@/api/wf'
import { Close, ArrowDown, Search } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Local, Session } from '@/utils/storage'
import { useRoute } from 'vue-router'

// 定义子组件向父组件传值/事件
const emit = defineEmits(['tool', 'change'])

interface Props {
  _id?: string
}

const props = defineProps<Props>()

const route = useRoute()
const { GetWorkFlowDesign, WorkFlowDesignDel, GetWorkFlowDesignList, GetWorkFlowDesignInsNames } =
  useWfApi()

// 定义变量内容
const copyId = ref('')
const connector = ref<string>(Local.get('Connector') || 'Bezier')
const queryId = props._id || route.query.id || ''
const search = ref('')
const visible = ref(false)
const state = reactive({
  toolList: [
    { icon: 'ele-View', title: '回到视图(Ctrl+F)', fnName: 'view' },
    { icon: 'ele-Refresh', title: '刷新', fnName: 'refresh' },
    { icon: 'ele-Plus', title: '新增工作流', fnName: 'add' },
    { icon: 'ele-Check', title: '提交', fnName: 'submit', hide: !!queryId },
    { icon: 'ele-Document', title: '粘贴', fnName: 'copy' },
    { icon: 'ele-Help', title: '帮助', fnName: 'help' },
    { icon: 'ele-Download', title: '下载', fnName: 'download' },
    { icon: 'ele-FullScreen', title: '全屏', fnName: 'fullscreen' },
    { icon: 'ele-Delete', title: '清空画布', fnName: 'del' }
  ]
})
const editRow = ref<WorkflowDesignRow>({
  created_on: '',
  descript: '',
  edges: [],
  flag: 'default',
  id: queryId || Session.get('workflow_row_id') || '',
  ins_name: '',
  name: '',
  nodes: [],
  ver: ''
})
// 表格数据
const gridData = ref<WorkflowDesignRow[]>([])
// 筛选后
const list = ref<WorkflowDesignRow[]>([])
// 流程实例
const ins_names = ref<SelectOptionType[]>([])

watch(
  () => copyId.value,
  (id) => {
    const tool = state.toolList.find((f) => f.fnName === 'copy')
    if (tool) {
      tool.hide = !id
      const row = list.value.find((f) => f.id === id)
      if (row) {
        tool.title = `粘贴 - ${row.name}`
      }
    }
  },
  { immediate: true }
)

// 搜索全表
const searchEvent = () => {
  const filterVal = String(search.value).trim().toLowerCase()
  if (filterVal) {
    const filterRE = new RegExp(filterVal, 'gi')
    const searchProps = ['name', 'ins_name', 'created_on', 'descript']
    const rest = gridData.value.filter((item: any) =>
      searchProps.some((key) => String(item[key]).toLowerCase().indexOf(filterVal) > -1)
    )
    list.value = rest.map((row) => {
      const item: any = Object.assign({}, row)
      searchProps.forEach((key) => {
        item[key] = String(item[key]).replace(
          filterRE,
          (match) => `<span class="color-primary">${match}</span>`
        )
      })
      return item
    })
  } else {
    list.value = gridData.value
  }
}

/**
 * 删除
 * @param row
 */
const onDeleteRow = (row: WorkflowDesignRow) => {
  ElMessageBox.confirm(`此操作将删除《${row.name}》，是否继续？`, '提示', {
    confirmButtonText: '删除工作流',
    cancelButtonText: '取消'
  })
    .then(() => {
      WorkFlowDesignDel(row.id).then(() => {
        initGridData()
        ElMessage.success('删除工作流成功。')
      })
    })
    .catch(() => {})
}

/**
 * 复制
 * @param row
 */
const onCopyRow = (row: WorkflowDesignRow) => {
  copyId.value = row.id
  ElMessage.warning(`${row.name} - 复制成功`)
  visible.value = false
}

const onConnectorChange = () => {
  Local.set('Connector', connector.value)
  onToolClick('connector')
}

/**
 * 表格行
 * @param row
 */
const onRadioChange: VxeTableEvents.RadioChange<WorkflowDesignRow> = ({ row }) => {
  handleCurrentChange(row)
}

/**
 * 选择
 * @param row
 */
const handleCurrentChange = (row?: WorkflowDesignRow) => {
  if (row && row.id) {
    GetWorkFlowDesign(row.id).then(({ data }) => {
      // 由于之前的版本BUG 保存了重复连线，这里获取时删除没用的连线，以便于下次编辑时删掉
      data.edges = data.edges.filter((f) => {
        const source = data.nodes.some((s) => s.id === f.sourceId)
        const target = data.nodes.some((s) => s.id === f.targetId)
        return target && source
      })

      editRow.value = data
      Session.set('workflow_row_id', data.id)
      visible.value = false
      setTimeout(() => {
        emit('change', unref(editRow))
      }, 300)
    })
  } else {
    editRow.value = {
      created_on: '',
      descript: '',
      edges: [],
      flag: 'default',
      id: '',
      ins_name: '',
      name: '',
      nodes: [],
      ver: ''
    }
    emit('change', unref(editRow))
  }
}

/**
 * 设置 tool 标题
 */
const setToolTitle = computed(() => {
  return `${editRow.value?.name || '请选择'} - 工作流`
})

/**
 * 顶部工具栏
 * @param fnName
 */
const onToolClick = (fnName: string) => {
  if (fnName === 'refresh') {
    handleCurrentChange(unref(editRow))
  } else if (fnName === 'add') {
    handleCurrentChange()
  } else if (fnName === 'copy') {
    if (copyId.value) {
      GetWorkFlowDesign(copyId.value).then(({ data }) => {
        // 由于之前的版本BUG 保存了重复连线，这里获取时删除没用的连线，以便于下次编辑时删掉
        data.edges = data.edges.filter((f) => {
          const source = data.nodes.some((s) => s.id === f.sourceId)
          const target = data.nodes.some((s) => s.id === f.targetId)
          return target && source
        })
        setTimeout(() => {
          emit('tool', fnName, data)
        }, 300)
      })
    }
  } else emit('tool', fnName, unref(editRow))
}

/**
 * 获取实例
 */
const initInsNames = () => {
  GetWorkFlowDesignInsNames().then(({ data }) => {
    const list: SelectOptionType[] = []
    for (const k in data) {
      list.push({
        value: k,
        label: data[k]
      })
    }
    ins_names.value = list
  })
}

/**
 * 获取工作流列表
 */
const initGridData = () => {
  GetWorkFlowDesignList().then(({ data }) => {
    gridData.value = data
    searchEvent()
    nextTick(() => {
      if (!data.some((s) => s.id === editRow.value.id)) {
        editRow.value.id = data[0].id
      }
      handleCurrentChange(unref(editRow))
    })
  })
}

onMounted(() => {
  initInsNames()
  initGridData()
})

defineExpose({ initGridData, onToolClick })
</script>

<style scoped lang="scss">
.workflow-tool {
  padding: 5px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--el-border-color-light, #ebeef5);
  color: var(--el-text-color-primary);

  .workflow-tool-right {
    flex: 1;
    display: flex;
    justify-content: flex-end;
  }

  &-icon {
    padding: 3px 5px;
    cursor: pointer;
    color: var(--next-bg-topBarColor);
    display: flex;
    align-items: center;
    border: var(--el-border-width) var(--el-border-style) var(--el-border-color);
    border-radius: 4px;
    margin-left: 5px;

    &.danger {
      color: var(--el-color-danger);
      border-color: var(--el-color-danger);
    }

    &.warning {
      color: var(--el-color-warning);
      border-color: var(--el-color-warning);
    }

    &.primary {
      color: var(--el-color-primary);
      border-color: var(--el-color-primary);
    }

    &:hover {
      background: rgba(0, 0, 0, 0.04);

      i {
        display: inline-block;
        animation: logoAnimation 0.3s ease-in-out;
      }
    }
  }
}
</style>
